package com.askyjt.videosearch.service.impl;

import com.askyjt.videosearch.bo.SocketDTO;
import com.askyjt.videosearch.common.constant.Constant;
import com.askyjt.videosearch.common.constant.MilvusParamEnum;
import com.askyjt.videosearch.config.MilvusConfig;
import com.askyjt.videosearch.entity.Picture;
import com.askyjt.videosearch.mapper.PictureMapper;
import com.askyjt.videosearch.service.PictureService;
import com.askyjt.videosearch.util.Result;
import com.askyjt.videosearch.util.SocketUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.milvus.client.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author yangjintao
 * @since 2020-11-05
 */
@Slf4j
@Service
public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture> implements PictureService {
    @Resource
    private PictureMapper pictureMapper;

    @Resource
    private MilvusConfig milvusConfig;

    @Override
    public List<Picture> searchPicture(String picturePath, Integer topK) {
        Map<String, String> parameters = new HashMap<>(8);
        parameters.put(MilvusParamEnum.IMG_PATH.getParamName(), picturePath);
        parameters.put(MilvusParamEnum.TABLE_NAME.getParamName(), Constant.MILVUS_PICTURE_TABLE);
        parameters.put(MilvusParamEnum.TOP_K.getParamName(), topK.toString());
        //调用socket搜索数据。
        SocketDTO socketDTO = SocketDTO.builder().method(Constant.SEARCH_VIDEO_OR_IMG).parameter(parameters).build();
        Result<Map<String, List<String>>> result = SocketUtil.remoteCallSearch(socketDTO);
        AtomicInteger index = new AtomicInteger(-1);
        //解析收到的数据并进行封装
        if (result != null && result.getCode() == Result.SUCCESS) {
            List<Long> milvusIds = result.getData().get(MilvusParamEnum.MILVUS_IDS.getParamName())
                    .stream().map(Long::valueOf).collect(Collectors.toList());
            List<String> disList = result.getData().get(MilvusParamEnum.MILVUS_DISLIST.getParamName());
            HashMap<Long, Double> milvusMap = new HashMap<>(8);
            milvusIds.forEach(mId -> milvusMap.put(mId, Double.valueOf(disList.get(index.incrementAndGet()))));
            List<Picture> pictures = pictureMapper.selectList(new QueryWrapper<Picture>().in(Picture.MILVUS_ID, milvusIds));
            pictures.forEach(x -> x.setDistance(milvusMap.get(x.getMilvusId())));
            //根据distance排序并返回
            return pictures.stream().sorted(Comparator.comparingDouble(Picture::getDistance)).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public Boolean savePicture(Picture picture) {
        HashMap<String, String> parameters = new HashMap<>(8);
        parameters.put(MilvusParamEnum.KEYFRAME_PATH.getParamName(), picture.getImageUrl());
        parameters.put(MilvusParamEnum.TABLE_NAME.getParamName(), Constant.MILVUS_PICTURE_TABLE);
        SocketDTO socketDTO = SocketDTO.builder().method(Constant.SAVE_FEATS).parameter(parameters).build();
        Result<Map<String, List<String>>> result = SocketUtil.remoteCallAdd(socketDTO);
        if (result != null && result.getCode() == Result.SUCCESS) {
            Long milvusId = Long.valueOf(result.getData().get(MilvusParamEnum.MILVUS_IDS.getParamName()).get(0));
            picture.setMilvusId(milvusId);
            return picture.insert();
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer deletePicture(List<Long> milvusIds) throws InterruptedException {
//        List<Picture> pictures = pictureMapper.selectBatchIds(milvusIds);
//        删除存储的图片，暂时仅使用逻辑删除。
//        if (CollectionUtils.isNotEmpty(pictures)) {
//            pictures.stream().map(pic -> {
//                File file = new File(pic.getImageUrl());
//                boolean delete = false;
//                if (file.exists() && file.isFile()) {
//                    delete = file.delete();
//                }
//                return null;
//            });
//        }
        int result = pictureMapper.deleteBatchIds(milvusIds);
        if (result > 0) {
            MilvusClient client = null;
            try {
                client = milvusConfig.getMilvusClient();
                Response response = client.deleteEntityByID(Constant.MILVUS_PICTURE_TABLE, milvusIds);
                log.info("删除milvus向量结果： code：" + response.getStatus().getCode() + " message" + response.getMessage());
            } catch (ConnectFailedException e) {
                e.printStackTrace();
            }finally {
                if (client != null) {
                    client.disconnect();
                }
            }
        }
        return result;
    }

}
